//
//  CustomNavController.m
//  Knowbox
//
//  Created by LiuXubin on 14/11/7.
//  Copyright (c) 2014年 knowin. All rights reserved.
//

#import "SimDragNavController.h"
#import "UIViewController+SimDragNavVC.h"
#import "UIView+SimAdditions.h"
#import "SimDefine.h"

#define kMaxDuration 0.4
#define kMinScale 0.9
#define kMaxMaskAlpha 0.6

@interface SimDragNavController () <UIGestureRecognizerDelegate, UINavigationControllerDelegate>

@property (nonatomic, assign) BOOL isMoving;
@property (nonatomic, assign) BOOL isTabShowChanged;
@property (nonatomic, strong) UIViewController *delayPopVc;
@property (nonatomic, strong) UIPanGestureRecognizer *recognizer;
@property (nonatomic, assign) CGPoint startTouch;
@property (nonatomic, strong) UIView *blackMask;
@property (nonatomic, strong) UIView *backgroundView;
@property (nonatomic, strong) NSMutableArray *screenShotsList;
@property (nonatomic, strong) UIImageView *lastScreenShotView;
@property (nonatomic, strong) UIView *curScreenShotView;
@property (nonatomic, strong) UIView *disableActionView;

@end

@implementation SimDragNavController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.delegate = self;
}

- (NSArray *)doPopViewToController:(UIViewController *)popToVc animated:(BOOL)animated{
    NSArray *vcs = self.viewControllers;
    NSMutableArray *popVcs = [NSMutableArray array];
    NSInteger index = vcs.count - 1;
    for (; index >= 1; index--) {
        UIViewController *vc = [vcs objectAtIndex:index-1];
        if(vc == popToVc){
            if (index < self.screenShotsList.count) {
                [self.screenShotsList removeObjectsInRange:NSMakeRange(index, self.screenShotsList.count-index)];
            }
            
            if(animated) {
                self.isTabShowChanged = YES;// (self.topViewController.hidesBottomBarWhenPushed != popToVc.hidesBottomBarWhenPushed);
                [self prepareForDrag];
                [self moveViewWithX:0];
                if (self.isTabShowChanged) {
                    [super popToViewController:popToVc animated:YES];
                }
                else{
                    self.delayPopVc = popToVc;
                }
                [self finishDragWith:self.view.width completion:nil];
            }
            else{
                [self finishDrag];
                [super popToViewController:popToVc animated:NO];
            }
            [self.screenShotsList removeLastObject];
            
            break;
        }
        else{
            [popVcs addObject:[vcs objectAtIndex:index]];
        }
    }
    
    return popVcs;
}

- (void)doPushViewController:(UIViewController *)viewController{
    self.isTabShowChanged =  NO; //(self.topViewController.hidesBottomBarWhenPushed != viewController.hidesBottomBarWhenPushed);
    [super pushViewController:viewController animated:self.isTabShowChanged];
    [self prepareForDrag];
    [self moveViewWithX:self.curScreenShotView.width];
    [self finishDragWith:0 completion:nil];
}


- (void)prepareForDrag{
    self.isMoving = YES;
    
    if (!self.backgroundView){
        self.backgroundView = [[UIView alloc]initWithFrame:self.view.window.bounds];
        self.backgroundView.backgroundColor = [UIColor blackColor];
        
        _blackMask = [[UIView alloc]initWithFrame:self.backgroundView.bounds];
        _blackMask.backgroundColor = [UIColor blackColor];
        [self.backgroundView addSubview:_blackMask];
    }
    
    if (!self.disableActionView) {
        _disableActionView = [[UIView alloc]initWithFrame:self.view.window.bounds];
    }
    
    self.blackMask.alpha = 0.0f;
    if (self.lastScreenShotView) {
        [self.lastScreenShotView removeFromSuperview];
    }
    UIImage *lastScreenShot = [self.screenShotsList lastObject];
    self.lastScreenShotView = [[UIImageView alloc] initWithImage:lastScreenShot];
    [self.backgroundView insertSubview:self.lastScreenShotView belowSubview:self.blackMask];
    
    if (!self.isTabShowChanged) {
        if (self.tabBarController) {
            self.curScreenShotView = self.tabBarController.view;
        }
        else{
            self.curScreenShotView = self.view;
        }
    }
    else{
        UIImage *curImage = nil;
        if (self.tabBarController) {
            curImage =[self capture:self.tabBarController.view];
        }
        else{
            curImage =[self capture:self.view];
        }
        self.curScreenShotView = [[UIImageView alloc] initWithImage:curImage];
        [self.view.window addSubview:self.curScreenShotView];
    }
    
    [self.curScreenShotView.superview insertSubview:self.backgroundView belowSubview:self.curScreenShotView];
    [self.curScreenShotView.superview addSubview:self.disableActionView];
}

- (UIViewController *)popViewControllerAnimated:(BOOL)animated{
    if (self.viewControllers.count >= 2) {
        if (self.viewControllers.count == 2) {
            [self.view removeGestureRecognizer:self.recognizer];
        }
        
        UIViewController *rtVc = [self.viewControllers objectAtIndex:self.viewControllers.count-2];
        [self doPopViewToController:rtVc animated:animated];
        return rtVc;
    }
    else{
        return [super popViewControllerAnimated:animated];
    }
}

- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated{
    return  [self doPopViewToController:viewController animated:animated];
}

- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated{
    UIViewController *rootVc = [self.viewControllers objectAtIndex:0];
    return  [self doPopViewToController:rootVc animated:animated];
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
    @autoreleasepool {
        if (self.viewControllers.count > 0) {
            UIImage *curImage = nil;
            if (self.tabBarController) {
                curImage =[self capture:self.tabBarController.view]; //APP_DELEGATE.window。
            }
            else{
                curImage =[self capture:self.view];
            }
            if (!curImage) {
                return;
            }
            
            if(!_screenShotsList){
                _screenShotsList = [NSMutableArray array];
            }
            [_screenShotsList addObject:curImage];
            
            if (self.viewControllers.count == 1) {
                if (!_recognizer) {
                    _recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureReceive:)];
                    _recognizer.delegate = self;
                    [_recognizer delaysTouchesBegan];
                }
                [self.view addGestureRecognizer:self.recognizer];
            }
            
        }
        
        if (animated) {
            [self doPushViewController:viewController];
        }
        else{
            [super pushViewController:viewController animated:NO];
            [self finishDrag];
        }
    }
}

- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated{
    NSArray *preVcs = self.viewControllers;
    NSMutableArray *newScreenShots = [NSMutableArray array];
    for (int i = 0; i < viewControllers.count-1; i++) {
        UIViewController *curVc = [viewControllers objectAtIndex:i];
        NSUInteger preVcIndex = [preVcs indexOfObject:curVc];
        UIImage *screenShot = nil;
        if (preVcIndex != NSNotFound) {
            //如果在之前的Vc中，取之前的Vc的图片
            screenShot = [self.screenShotsList objectAtIndex:preVcIndex];
        }
        else{
            //之前Vc中不存在，没有截过图，只能空的图
            screenShot = [[UIImage alloc] init];
        }
        [newScreenShots addObject:screenShot];
    }
    self.screenShotsList = newScreenShots;
    
    [super setViewControllers:viewControllers animated:animated];
}

- (UIImage *)capture:(UIView *)view{
    //[view.layer layoutIfNeeded]; //有时layout没生成，需先调用这个再截屏
    
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, view.window.screen.scale);
    if (ABOVE_IOS7) {
        [view drawViewHierarchyInRect:view.frame afterScreenUpdates:NO];
    }
    else{
        CGContextRef curContext = UIGraphicsGetCurrentContext();
        CGContextClipToRect(curContext, CGRectMake(0, kApplicationTop, view.width, view.height-kApplicationTop));
        [view.layer renderInContext:curContext];

    }
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

- (void)finishDragWith:(CGFloat)x completion:(void(^)(void))completion{
    int dis = fabs(self.curScreenShotView.left-x);
    NSTimeInterval duration = dis >= self.curScreenShotView.width/2 ? kMaxDuration : kMaxDuration*dis*2/self.curScreenShotView.width;
    [UIView animateWithDuration:duration
                     animations:^{
                         [self moveViewWithX:x];
                     }
                     completion:^(BOOL finished) {
                         if(completion){
                             completion();
                         }
                         [self finishDrag];
                     }];
}

- (void)finishDrag{
    self.backgroundView.transform = CGAffineTransformIdentity;
    [self.backgroundView removeFromSuperview];
    [self.disableActionView removeFromSuperview];
    if (!self.isTabShowChanged) {
        self.curScreenShotView.left = 0;
    }
    else{
        [self.curScreenShotView removeFromSuperview];
    }
    if (self.delayPopVc) {
        [super popToViewController:self.delayPopVc animated:NO];
    }
    self.curScreenShotView = nil;
    self.isMoving = NO;
    self.isTabShowChanged = NO;
    self.delayPopVc = nil;
}

- (void)moveViewWithX:(CGFloat)x{
    x = MIN(self.view.width, x);
    x = MAX(0, x);
    self.curScreenShotView.left = x;
    
    float scale = (x*(1-kMinScale)/self.backgroundView.width)+kMinScale;
    self.lastScreenShotView.transform = CGAffineTransformMakeScale(scale, scale);
    self.lastScreenShotView.center = CGPointMake(self.backgroundView.width/2, self.backgroundView.height/2);
    
    self.blackMask.alpha = kMaxMaskAlpha-(x*kMaxMaskAlpha/self.lastScreenShotView.width);
}

#pragma mark -  UINavigationControllerDelegate Method
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.interactivePopGestureRecognizer.enabled = NO;
    }
}

#pragma mark -  UIPanGestureRecognizer Method
- (void)panGestureReceive:(UIPanGestureRecognizer *)recoginzer{
    if (self.viewControllers.count <= 1)
        return;
    CGPoint touchPoint = [recoginzer locationInView:self.view.window];
    if (recoginzer.state == UIGestureRecognizerStateBegan) {
        self.startTouch = touchPoint;
        [self prepareForDrag];
    }else if (recoginzer.state == UIGestureRecognizerStateEnded || recoginzer.state == UIGestureRecognizerStateCancelled || recoginzer.state == UIGestureRecognizerStateFailed){
        if (touchPoint.x - self.startTouch.x > 60.0f){
            [self finishDragWith:self.view.width completion:^{
                self.view.left = 0;
                [self popViewControllerAnimated:NO];
            }];
        }
        else{
            [self finishDragWith:0 completion:nil];
        }
    }
    else if(recoginzer.state == UIGestureRecognizerStateChanged){
        if (self.isMoving) {
            [self moveViewWithX:touchPoint.x - self.startTouch.x];
        }
    }
}

#pragma mark - UIGestureRecognizer

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if (self.recognizer == gestureRecognizer) {
        return [self.topViewController shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer];
    }
    return NO;
}


- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if (self.forbiddenDrag) {
        return NO;
    }
    if (self.recognizer == gestureRecognizer) {
        
        return [self.topViewController shouldBeginDragGesture:gestureRecognizer receiveTouch:touch];
    }
    
    return YES;
}

- (void)setForbiddenDrag:(NSNumber *)forbiddenDrag {
    _forbiddenDrag = forbiddenDrag.boolValue;
}

@end
